<?php
global $CFG;
require_once($CFG->dirroot . '/blocks/formal_langs/langs_src/tools/JLexPHP/jlex.php');
require_once($CFG->dirroot . '/blocks/formal_langs/langs_src/tools/pos/pos_tagger.php');
require_once($CFG->dirroot . '/blocks/formal_langs/tokens_base.php');
require_once($CFG->dirroot . '/blocks/formal_langs/tokens/eng_simple.php');
require_once($CFG->dirroot . '/blocks/formal_langs/langs_code/predefined/eng_simple_parser.php');
%%

%class eng_simple_lexer
%function next_token
%char
%line
%state STRING

WORD       = [a-zA-Z0-9]+
V          = (bites|pets|rules|fly|swim)
N          = (ball|bat|bed|book|boy|bun|can|cake|cap|car|cat|cow|cub|cup|dad|day|dog|doll|dust|fan|fly|feet|girl|gun|hall|hat|hen|jar|kite|man|map|men|mom|pan|pet|pie|pig|pot|rat|son|sun|toe|tub|van|apple|arm|banana|bike|bird|book|chin|clam|class|clover|club|corn|crayon|crow|crown|crowd|crib|desk|dime|dirt|dress|fang|field|flag|flower|fog|game|heat|hill|home|horn|hose|joke|juice|kite|lake|maid|mask|mice|milk|mint|meal|meat|moon|mother|morning|name|nest|nose|pear|pen|pencil|plant|rain|river|road|rock|room|rose|seed|shape|shoe|shop|show|sink|snail|snake|snow|soda|sofa|star|step|stew|stove|straw|string|summer|swing|table|tank|team|tent|test|toes|tree|vest|water|wing|winter|woman|women|alarm|animal|aunt|bait|balloon|bath|bead|beam|bean|bedroom|boot|bread|brick|brother|camp|chicken|children|crook|deer|dock|doctor|downtown|drum|dust|eye|family|father|fight|flesh|food|frog|goose|grade|grandfather|grandmother|grape|grass|hook|horse|jail|jam|kiss|kitten|light|loaf|lock|lunch|lunchroom|meal|mother|notebook|owl|pail|parent|park|plot|rabbit|rake|robin|sack|sail|scal)
DT         = (the|a)
WS         = [ \t\r\n]
P          = (as|at|by|but|for|from|in|of|off|on|out|over|to|down|up|with|about|into|after|beneath|under|above|near)
    
%{
    private $token_count = 0;

    private $tagger = null;

    public $errors = array();

    private $N_tags  = array('NN', 'NN$', 'NNS', 'NNS$', 'NP', 'NP$', 'NPS',
                             'NPS$', 'NR','PN$', 'PP', 'PP$$', 'PPL', 'PPLS',
                             'PPO', 'PPS', 'PPSS', 'WP$', 'WPS');
    private $V_tags  = array('VB', 'VBD', 'VBG', 'VBN', 'VBZ');
    private $DT_tags = array('AT', 'DT', 'DTI', 'DTS', 'DTX');
    private $P_tags  = array('IN');

    private function return_token_by_tagger($text) {
        $tags = $this->tag($text);
        if (count($tags) == 1) {
            $tag = $tags[0]['tag'];
            /* Produce classname and object instance to return. */
            if (in_array($tag, $N_tags)) {
                return $this->return_token(eng_simple_yyParser::N, $this->yytext(), 'N');
            } else if (in_array($tag, $V_tags)) {
                return $this->return_token(eng_simple_yyParser::V, $this->yytext(), 'V');
            } else if (in_array($tag, $DT_tags)) {
                return $this->return_token(eng_simple_yyParser::DT, $this->yytext(), 'DT');
            } else if (in_array($tag, $P_tags)) {
                return $this->return_token(eng_simple_yyParser::P, $this->yytext(), 'P');
            }
        } else {
            return false;
        }
    }

    private function return_token($type, $value, $desc) {
        $res = null;
        $classname = 'block_formal_langs_token_';
        switch ($type) {
        case eng_simple_yyParser::PERIOD      : $classname .= "punctuation"; break;
        case eng_simple_yyParser::EXCLAMATION : $classname .= "punctuation"; break;
        case eng_simple_yyParser::QUESTION    : $classname .= "punctuation"; break;
        case eng_simple_yyParser::DT          : $classname .= "article"; break;
        default :                               $classname .= "word"; break;
        }
        $res = new $classname(NULL, $type, $value, $this->return_pos(), $this->token_count);
        // create token object
        $res->set_description($desc);
        // increase token count
        $this->token_count++;

        return $res;
    }

    private function return_pos() {
        $begin_line = $this->yyline;
        $begin_col = $this->yycol;

        if(strpos($this->yytext(), '\n')) {
            $lines = explode("\n", $this->yytext());
            $num_lines = count($lines);
            
            $end_line = $begin_line + $num_lines - 1;
            $end_col = strlen($lines[$num_lines -1]);
        } else {
            $end_line = $begin_line;
            $end_col = $begin_col + strlen($this->yytext());
        }
        
        $res = new block_formal_langs_node_position($begin_line, $end_line, $begin_col, $end_col);
        
        return $res;
    }
    
%}

%init{
    global $CFG;
    $this->tagger = new PosTagger($CFG->dirroot . '/blocks/formal_langs/langs_src/tools/pos/lexicon.txt');
%init}

%eof{

%eof}

%%

<YYINITIAL> "."  { return $this->return_token(eng_simple_yyParser::PERIOD, $this->yytext(), "PERIOD"); }
<YYINITIAL> "!"  { return $this->return_token(eng_simple_yyParser::EXCLAMATION, $this->yytext(), "EXCLAMATION"); }
<YYINITIAL> "?"  { return $this->return_token(eng_simple_yyParser::QUESTION, $this->yytext(), "QUESTION"); }
<YYINITIAL> {P}  { return $this->return_token(eng_simple_yyParser::P, $this->yytext(), "P"); }
<YYINITIAL> {N}  { return $this->return_token(eng_simple_yyParser::N, $this->yytext(), "N"); }
<YYINITIAL> {V}  { return $this->return_token(eng_simple_yyParser::V, $this->yytext(), "V"); }
<YYINITIAL> {DT} { return $this->return_token(eng_simple_yyParser::DT, $this->yytext(), "DT"); }

<YYINITIAL> {WORD} {
    $token = $this->return_token_by_tagger($this->yytext());
    if ($token) {
        return $token;
    }
 }

<YYINITIAL> {WS}+ {}

. { /* process bad input */
    $error = array();
    $error['line'] = $this->yyline;
    $error['column'] = $this->yycol;
    $error['input'] = $this->yytext();

    $this->errors[] = $error;
 }
